package mymyoux.io.mserverconnectorClasses
{
	import mymyoux.core.IObject;
	import mymyoux.events.ErrorEvent;
	import mymyoux.events.MEventDispatcher;
	import mymyoux.events.MServerIdentifierEvent;
	import mymyoux.utils.Hash;
	import mymyoux.utils.StringUtils;
	        /**
         * MServerIdentifier dispatche l'event update_infos
         * quand l'utilisateur met à jour ses informations.
         * @eventType mymyoux.events.MServerIdentifierEvent
         */
        [Event(name="update_infos", type="mymyoux.events.MServerIdentifierEvent")]
	/**
	 * MServerIdentifier permet d'enregistrer des données sur chacun des joueurs y compris le joueur actuel.
	 * @author Mymyoux
	 * @version 2.0
	 */
	public class MServerIdentifier extends MEventDispatcher implements IObject
	{
	 /**
	 * Contient toutes les informations du joueur. idx est la seule valeur obligatoire
	 */
		protected var infos:Hash;
	 /**
	 * crée un objet de type MServerIdentifier.
	 * @param idx Enregistre un entier unique représentant le joueur sur les MServeurs.
	 * @throws mymyoux.events.ErrorEvent Renvoie une erreur si l'idx est égal à 0.
	 */
		public function MServerIdentifier(idx:int)
		{
			if(idx<0){
				throw(new ErrorEvent("L'idx doit nécessairement être supérieur à 0!",9));
			}
			infos=new Hash();
			put("idx",idx);
		}
		/**
		 * idx du joueur.
		 */
		public function get idx():uint{
			return StringUtils.toNumber(getValue("idx")) as uint;
		}

	 /**
	 * Enregistre une donnée du joueur.
	 * @param name Nom de la donnée à enregistrer.
	 * @param value Valeur de la donnée à enregistrer.
	 * @throws mymyoux.events.ErrorEvent Une erreur est renvoyée si le nom ou la valeur sont nuls ou bien s'ils contiennent le caractère '§'. 
	 * Une erreur est également renvoyée si le nom contient le caractère '='.
	 */
		public function put(name:String,value:Object):void{
			//Autorisé qu'une fois à avoir un idx
			if(name!="idx" || !hasValue("idx")){
				var valeur:String=value.toString();
				if(valeur==null || valeur.indexOf("§")>-1 || valeur.length==0){
					throw(new ErrorEvent("La valeur passée en paramètre ne doit pas contenir de '§' à l'intérieur et ne dois pas être nulle.",10));
				}
				if(name==null || name.indexOf("§")>-1 || name.indexOf("=")>-1 || name.length==0){
					throw(new ErrorEvent("Le nom de la valeur ne doit pas contenir de '§' ou de '=' à l'intérieur et ne dois pas être nul",11));
				}
				if(infos.containsKey(name)){
					if(infos.get(name)==value){
						return
					}
				}
				infos.put(name,valeur);
				dispatchEvent(new MServerIdentifierEvent(MServerIdentifierEvent.UPDATE));
			}
		}
	 /**
	 * Récupère la valeur de la donnée.
	 * @param name Nom de la donnée à récupérer.
	 * @return La valeur de la donnée ou "" si la donnée n'existe pas;
	 */
		public function getValue(name:String):String{
			if(name.length==0){
				return "";
			}
			var valeur:Object=infos.get(name);
			if(valeur==null){
				return "";
			}else{
				return valeur.toString();
			}
		}
	/**
	 * Indique si oui ou non le MServerIdentifier contient la donnée associée.
	 * @param name Nom de la donnée.
	 * @return Un boolean indiquant true si la donnée existe et false sinon.
	 */
		public function hasValue(name:String):Boolean{
			return getValue(name).length>0;
		}
	 /**
	 * Récupère la liste des noms de données enregistrées.
	 * @return Un array contenant la liste des noms.
	 */
		public function getNames():Array{
			return infos.getKeys();
		}
	/**
	 * Supprime une donnée du joueur.
	 * @param name Nom de la donnée à supprimer.
	 */
		public function rem(name:String):void{
			if(name.length>0){
				if(name!="idx"){
					if(infos.containsKey(name)){
						infos.remove(name);
						dispatchEvent(new MServerIdentifierEvent(MServerIdentifierEvent.UPDATE));
					}
				}
			}
		}
	 /**
	 * Efface toutes les données du joueur à l'exception de son idx.
	 */
		public function clear():void{
			var idx:String=infos.get("idx").toString();
			infos.clear();
			infos.put("idx",idx);
		}
	 /**
	 * Crée un nouvel objet MServerIdentifier à partir d'une chaine de caractères.
	 * @param identifier Chaine de caractères permettant de générer l'objet.
	 * @return Le MServerIdentifier généré par la chaine de caractère.
	 * @throws mymyoux.events.ErrorEvent Renvoie une erreur si la chaine de caractères n'est pas valide.
	 */
		 static public function unserialize(identifier:String):MServerIdentifier{
		 	var error:Boolean=false;
		 	var first:Array=identifier.split("§§");
		 	var second:Array;
		 	var names:Array=new Array();
		 	var valeurs:Array=new Array();
		 	for(var i:String in first){
		 		if(first[i].length>0){
		 			second=first[i].split("=");
		 			if(second.length==2){
		 				if(second[1]==null || second[1].indexOf("§")>-1 || second[1].length==0 || second[0]==null || second[0].indexOf("§")>-1 || second[0].indexOf("=")>-1 || second[0].length==0){
		 					error=true;
		 					break;
		 				}
		 				names.push(second[0]);
		 				valeurs.push(second[1]);
		 			}
		 		}
		 	}
		 	var idx:int=names.indexOf("idx");
		 	if(idx==-1){
		 		error=true;
		 	}
		 	if(error){
		 		throw(new ErrorEvent("Unserialization impossible, chaine non reconnue",12));
		 		return null;
		 	}else{
		 		idx=StringUtils.toNumber(valeurs[idx]) as uint;
				var m:MServerIdentifier=new MServerIdentifier(idx);
				for(i in names){
					if(names[i]!="idx"){
						m.put(names[i],valeurs[i]);
					}
				}
				return m;
		 	}
		 }
	/**
	 * Fusionne identifier dans l'objet en cours.
	 * @param identifier Le MServerIdentifier à faire fusionner dans celui en cours.
	 */
	public function fusion(identifier:MServerIdentifier):void{
		if(identifier!=null){
			//on efface les données précédentes
			clear();
			var liste:Array=identifier.getNames();
			for(var i:String in liste){
				put(liste[i],identifier.getValue(liste[i]));
			}
		}
	}
	 /**
	 * Renvoie une chaine de caractère correspondant au MserverIdentifier.
	 * @return Une chaine de caractères résultant du MServerIdentifier.
	 */
		 public function serialize():String{
			var names:Array=infos.getKeys();
			var valeurs:Array=new Array();
			for(var i:String in names){
				valeurs.push(infos.get(names[i]));
			}
			var chaine:String="";
			for(i in names){
				chaine+="§"+names[i]+"="+valeurs[i]+"§";
			}
			return "§"+chaine+"§";
		 }
		 /**
		 * @inheritDoc 
		 */
		public override function equals(objet:IObject):Boolean{
			try{
				return StringUtils.toNumber(this.getValue("idx"))==StringUtils.toNumber((objet as MServerIdentifier).getValue("idx"));
			}catch(e:Error){
				return false;
			}
			return false;
		} /**
		 * @inheritDoc 
		 */
		public override function destroy():void{
			clear();
		}
		 /**
		 * @inheritDoc 
		 */
		public override function toString():String{
			 var names:Array=infos.getKeys();
				var valeurs:Array=new Array();
				for(var i:String in names){
					valeurs.push(infos.get(names[i]));
				}
				var chaine:String="";
				for(i in names){
					chaine+=" "+names[i]+"=\""+valeurs[i]+"\"";
				}
			return "[MServerIdentifier"+chaine+"]";
		}
	}
}